package birdsong.comm.implemented;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;

/**
 * Thread that handle a request from a client
 * This thread is allways waiting for a client message
 * @author group18
 *
 */
public class ClientHandler extends Thread {


	private Socket socket;
	private ObjectInputStream in;
	private ObjectOutputStream out;
	private ServerComm comm;
	
	private String clientNickName;

	private boolean know=false;


	private boolean connected=true;

	
	private boolean DEBUG = false;
	
	/**
	 * Uses a socket to the client
	 * 
	 * @param socket Socket that is opened to the client
	 * @param comm Class ServerComm
	 */
	public ClientHandler(Socket socket, ServerComm comm) {
		super();
		this.socket = socket;
		this.comm=comm;
		try {
			init();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}



	/**
	 * Opens the output and input streams of the socket
	 * 
	 * @throws IOException   if an I/O error occurs when creating the output stream or if the socket is not connected.
	 */
	private void init() throws IOException {
		out=new ObjectOutputStream(socket.getOutputStream());
		in=new ObjectInputStream(socket.getInputStream());

	}
	/**
	 * Sends the client Message
	 * 
	 * @param message Object type message
	 */
	public synchronized void sendMessage( ClientSideMessage message ){
		try {
			out.writeObject(message);
			out.reset();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	/**
	 * Creates a Thread that listens to the client
	 */
	@Override
	public void run() {

		Object objectReceived;
		
		while(connected){
			try {
				objectReceived = in.readObject();
				if(!know && objectReceived instanceof NewClientConnect ){	
					this.clientNickName=((NewClientConnect)objectReceived).getNickName();
					comm.updateHandlerOwner(clientNickName, this);
					know=true;
				}else if(objectReceived instanceof DisconnectClient){
					connected=false;
					comm.disconnectClientForced(this.clientNickName);
				}else if(objectReceived instanceof ServerSideMessage){
					if(DEBUG){
						System.out.println((ServerSideMessage)objectReceived);
					}
					comm.receiveMessageFromClient((ServerSideMessage)objectReceived);
				}
			} catch (SocketException e) {
				connected=false;
				comm.disconnectClientForced(this.clientNickName);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				//e.printStackTrace();
				connected=false;
				comm.disconnectClientForced(this.clientNickName);

			}
		}

	}

	/**
	 * Disconnects the client
	 */
	public void disconnect() {
		connected=false;

		try {
			socket.close();			
			in.close();
			out.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
		}

	}

}
